/*
    Marv the Miner for Nokia Series 30, 40 and 60 and for selected MIDP 1.0 supported phones
    Copyright (C) 2003-2004  Digital Entertainment Europe AS (http://www.digiment.no)

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
	
    If you have any questions, please contact support@digiment.no
*/
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.io.*;
import java.util.*;

class Dynamic
{
	static int T_A = 0;		// alien type
	static int T_M = 1;		// man type
	static int T_B = 2;		// bonus  type
	static int T_D = 3;		// default type
	static int T_T = 11;	// trap type
	static int image_index = 0;
	static int tx,ty,i,j,n,delay;

	int start_x,start_y;

	int phase = -1;

	int class_type;
	int type;
	int x,y,min_y;
	int dx,dy,sdx,sdy;
	int new_x,new_y;
	int jump_x,jump_y;
	int jumpIndex = -1;
	int last_dx,last_dy,y_border,bw;
	int timeUse;
	boolean visible, started;
	Vector v1,v2;

	int delay_range = 10;
	int delay2;
	boolean isFalling = false;
	boolean isFallen = false;

	boolean inUse = false;
	boolean alarm = false;

	CObject curObj = null,obj;
	CObject startObj = null;

	// animation variables
	int a[][] = null;
	int b[] = null;
	int a1;
	int a2;
	int time;
	int disp;
	boolean finished;
	boolean loop = true;

	Frame frame = null;

	Dynamic(int class_type,int type,int x,int y,CObject obj,Frame frame,String animation_name)
	{
		this.class_type = class_type;
		this.type = type;
		this.x = start_x = new_x = x;
		this.y = start_y = new_y = min_y = y;
		dx = dy = sdx = sdy = 0;
		curObj = startObj = obj;
		this.frame = frame;
		if (class_type == T_A) dx = 1;
		time = disp = 0;
		a1 = 0;
	    delay2 = 0;
		a2 = 1;
 		v1 = (Vector)Main.hAnims.get(animation_name);
 		a = null;
 		loop = true;
 		timeUse = 0;
	    bw = frame.fw >> 1;
	    if ((class_type == T_M) || (class_type == T_A)) bw = 0;
 		if (v1 != null)
 			if (v1.size() > 0)
 			{
		 		a = new int[v1.size()][];
		 		for (i = 0; i < a.length; i++)
		 		{
		    		v2 = (Vector)v1.elementAt(i);
		    		a[i] = null;
		    		if (v2 != null)
		    			if (v2.size() > 0)
		    			{
				    		a[i] = new int[v2.size()];
		 			        for (j = 0; j < a[i].length; j++)
		 			        {
		 			        	a[i][j] = ((Integer)v2.elementAt(j)).intValue();
		 			        	if (j > 0) a[i][j] *= frame.fw;
		 			        }
						}
		 		}
		 		v1 = null;
		 		v2 = null;
				a2 = 1 + Main.rnd(a[0].length - 1);
		    	time = Main.rnd(a[0][0]);
			}
		visible = true;
		isFalling = true;
		finished = false;
		started = false;
		inUse = false;
		phase = -1;
		restart();
	}

	void restart()
	{
		x = new_x = start_x;
		y = new_y = min_y = start_y;
		curObj = startObj;
		loop = true;
		inUse = false;
		isFalling = true;
		isFallen = false;
		visible = true;
		started = false;
		a1 = 0;
		if (class_type == T_M)
		{
			last_dx = Main.step;
			last_dy = 0;
			a1 = 1;
		}
	}

    void jump(int dir_x)
    {
   		if ((jumpIndex == -1) && (!isFalling) && (phase == -1))
    	{
			jumpIndex = 0;
			if (dir_x != 99) last_dx = dir_x;
			jump_x = x;
			jump_y = y;
			curObj = null;
		}
    }

    void shift(int delta_x,int delta_y)
    {
    	if (phase == -1)
    	{
   			if (jumpIndex == -1)
	    	{
    			last_dx = dx = delta_x;
   				last_dy = dy = delta_y;
	    	}
			dx = delta_x;
			dy = delta_y;
		}
    }

    void stop()
    {
    	if ((phase == -1) && (!isFalling)) dx = dy = 0;
    }

	void update()
	{
//		regenerate the monster
//		if (timeUse > 0)
//		{
//			timeUse --;
//			if (timeUse == 0)
//			{
//				restart();
//			}
//		}
		isFallen = false;
		if (inUse && (class_type == T_B))
		{
			new_x = x = Main.man.x;
			new_y = y = Main.man.y - 19;
		}
		if (((class_type == T_B) || (class_type == T_D)) && started) return;
		// if jumping
		if (jumpIndex != -1)
		{
           	tx = Main.fxp[jumpIndex];
           	ty = Main.fyp[jumpIndex];
           	if (last_dx < 0) tx = -tx;
           	if (last_dx == 0) tx = 0;

    		if (dx > 0 ) jump_x ++;
    		if (dx < 0 ) jump_x --;

           	new_x = jump_x + tx;
           	new_y = jump_y - ty;

           	sdx = dx = new_x - x;
           	sdy = dy = new_y - y;

           	if (++jumpIndex >= Main.fxp.length)
           	{
           		jumpIndex = -1;
           		isFalling = true;
           	}
		}

		// update position
    	if (curObj != null)
    	{
    		if (curObj.type == Main.C_P)
    		{
			    new_x = x + dx;
			    if (class_type == T_A)
			    {
			    	if (dx > 0)
			    	{
			    		if ((dx < 3) && (x - curObj.x1 > 5)) dx ++;
			    	}
			    	else
			    	{
			    		if ((dx > -3) && (curObj.x2 - x > 5)) dx --;
			    	}
			    }
            	if ((new_x - bw >= curObj.xmin) && (new_x + bw <= curObj.xmax))
            	{
        	    	new_y = (new_x - curObj.x1) * curObj.dy / curObj.dx + curObj.y1;
                   	if (class_type == T_M)
                   	{
                   		if (Main.state == 0)
                   		{
	            			n = (new_x - curObj.xmin) / 10;
            				if (n < curObj.blocks.length)
        	    			{
    	        				if (!(curObj.blocks[n]))
	            				{
	            					curObj.blocks[n] = true;
     								Main.obj = curObj;
     								Main.closed_blocks --;
     								Main.p_num = n;
     								Main.drawP();       					
    	        				}
	            			}
            			}
               			// search for a stair
               			for (i = 0; i < Main.aObj.length; i++)
           	    		{
               				obj = Main.aObj[i];
               				if ((obj.type == Main.C_Lift))
               				{
				            	if ((obj.x1 - (obj.fw >> 1) <= new_x) && (obj.x1 + (obj.fw >> 1) >= new_x) &&
				            		(new_y >= obj.my - 6) && (new_y <= obj.my + 2))
				            	{
				            		new_y = obj.my - 6;
           							curObj = obj;
          							break;
				            	}
               					
               				}
               				if (obj.type == Main.C_Slope)
               				{
               					if ((obj.y1 - 4 <= new_y) && (obj.y2 - 10 >= new_y))
               					{
           							tx = obj.x1 + (new_y - obj.y1) * obj.k;
               						if ((tx - 4 <= new_x) && (tx + 4 >= new_x))
               						{
               							dy = Main.step;
               							new_x = tx;
               							curObj = obj;
               							phase = 4;
               							break;
               						}
               					}

               				}
               				if (dx != 0)
               				{
        	       				if (obj.type == Main.C_Press)
        	       					if ((new_y - frame.fh <= obj.my) && (new_y - frame.fh >= obj.ymin) && 
        	       						(new_x + 15 > obj.x1) && (new_x - 15 < obj.x1))
        	       					{
        	       						new_x = x;
        	       						new_y = y;
//        	       						if (dx > 0) new_x += dx;
//        	       						if (dx < 0) new_x += dx;
        	       						dx = 0;
        	       					}
               				}
               				if (dy != 0)
               				{
        	       				if ((obj.type == Main.C_Teleport) && (dy < 0))
    	           				{
									if ((obj.x1 - 3 <= new_x) && (obj.x1 + 3 >= new_x) && 
										(obj.y1 - 2 <= new_y) && (obj.y1 + 2 >= new_y))
									{
										curObj = obj;
										x = new_x = obj.x1;
										y = new_y = obj.y1;
										dy = 0;
    									a1 = 14;
			    						finished = false;
		    							Main.state = 33;
										break;
									}
               					}
               					else
        	       				if (obj.type == Main.C_S)
    	           				{
	               					if ((((dy < 0) && (obj.ymax - 10 <= new_y) && (obj.ymax + 10 >= new_y)) ||
               						     ((dy > 0) && (obj.ymin - 10 <= new_y) && (obj.ymin + 10 >= new_y))) &&
               					    	 (obj.x1 - 8 <= new_x) && (obj.x1 + 8 >= new_x))
           	    					{
               							new_x = obj.x1;
               							new_y = dy < 0 ? obj.ymax: obj.ymin;
            	   						curObj = obj;
        	       						break;
    	       	    				}
	               				}
               				}
               			}
               			if (curObj != null)
							if ((dy < 0) && (curObj.type == Main.C_P)) jump(0);
                   	}
            	}
            	else
            	// check platform end
            	{
            	    if (class_type == T_M)
            	    {
            			isFalling = true;
            			curObj = null;
            		}
            		else
            	    if (class_type == T_A) 
            	    {
            			dx = (dx > 0) ? -1 : 1;
            			if (new_x - bw < curObj.x1)
            			{
            				new_x = curObj.x1 + bw;
            				new_y = curObj.y1;
            			}
            			if (new_x + bw > curObj.x2)
            			{
            				new_x = curObj.x2 - bw;
            				new_y = curObj.y2;
            			}
            	    }
            	}
    	    }
    	    else
    		if (curObj.type == Main.C_S)
    		{
            	if ((y >= curObj.ymin) && (y <= curObj.ymax))
            	{
				    new_y += dy;
				    new_x += dx;
				    if ((curObj.x1 - 5 > new_x) || (curObj.x1 + 5 < new_x))
				    {
				    	// falling from stair
				    	curObj = null;
				    	isFalling = true;
				    	new_x = x;
				    }
				    else
				    {
				   		if (dy < 0) a1 = 4;
			   			else
						if (dy > 0) a1 = 5;
						if (curObj.ymin + 12 >= y) a1 = 6;
				    }
            	}
            	else curObj = null;
    		}
    	    else
    		if (curObj.type == Main.C_M)
    		{
			    new_x += dx;
            	if ((curObj.mx - 5 <= new_x) && (curObj.mx + 5 >= new_x))
            	{
            	}
            	else
            	{
            		curObj = null;
            		isFalling = true;
            	}
				if (dy < 0) jump(0);
    		}
    	    else
    		if (curObj.type == Main.C_Lift)
    		{
			    new_x += dx;
            	if ((curObj.x1 - (curObj.fw >> 1) <= new_x) && (curObj.x1 + (curObj.fw >> 1) >= new_x))
            	{
            	}
            	else
            	{
            		curObj = null;
            		isFalling = true;
            	}
				if (dy < 0) jump(0);
    		}
    	    else
    		if (curObj.type == Main.C_Sucker)
    		{
    			new_x = x + dx;
    			new_y = y + dy;
    			if (phase == 0)
    			{
    				dy = -4;
    				if (y < curObj.ymin)
    				{
    					new_y = curObj.ymin - frame.h;
    					phase = 1;
    					dy = 0;
    					dx = curObj.x1 < curObj.x2 ? 4 : - 4;
    				}
    			}
    			if (phase == 1)
    			{
    				if (((dx > 0) && (x > curObj.x2)) || ((dx < 0) && (x < curObj.x2)))
    				{
		    			y_border = obj.y2;
    					new_x = curObj.x2;
    					new_y = curObj.y2;
    					phase = 2;
    					dx = 0;
    					dy = 0;
    					curObj = null;
    				}
    			}
    		}
    	    else
    		if (curObj.type == Main.C_Slope)
    		{
    			dy = Main.step;
    			dx = curObj.k * Main.step;
    			new_x = x + dx;
    			new_y = y + dy;

				for (i = 0; i < Main.aObj.length; i++)
	    		{
    				obj = Main.aObj[i];
    				if ((obj.type == Main.C_P))
		    		if ((obj.x1 - 1 <= new_x) && (obj.x2 + 1 >= new_x))
		    		{
						ty = obj.y1 + (x - obj.x1) * obj.dy / obj.dx;
		    			if ((ty - y >= - 4) && (ty - y <= 4))
		    			{
		    				for (j = -6; j <= 6; j += 6)
		    				{
	    	        			n = (new_x - obj.xmin + j) / 10;
    	        				if (n < obj.blocks.length)
	        	    			{
    	        					if (!(obj.blocks[n]))
	            					{
	            						obj.blocks[n] = true;
     									Main.obj = obj;
     									Main.closed_blocks --;
     									Main.p_num = n;
     									Main.drawP();       					
    		        				}
		            			}
		    				}
		    			}
		    		}
    			}

    			if (new_y >= curObj.y2)
    			{
    				curObj = null;
    				phase = -1;
    				isFalling = true;
    			}
    		}
    	    else
    		if (curObj.type == Main.C_Teleport)
    		{
    		}
    		min_y = new_y;
	    }
	    else
	    // on floor
    	{
    		//(!isFalling) && (jumpIndex == -1)
	    	if (y + 1 >= Main.a_h)
	    	{
	    		phase = -1;
	    		isFallen = true;
	    		dx = 0;
	    	}
	    	if (isFalling)
	    	{
	    		if (dx > 0 ) dx = 1;
	    		if (dx < 0 ) dx = -1;
	    	}
    		new_x = x + dx;
//			if (dy < 0) jump(0);
    	}

		// if current object is null
		if ((curObj == null) && (y + 1 < Main.a_h))
		{
		    for (i = 0; (i < Main.aObj.length) && (curObj == null); i++)
		    {
		    	obj = Main.aObj[i];
		    	if ((dy > 0) || (jumpIndex == -1))
		    	{
			    	if (obj.type == Main.C_P)
			    	{
			    		if (((obj.x1 - 1 <= new_x) && (obj.x2 >= new_x) && (dx >= 0)) ||
			    			((obj.x1 <= new_x) && (obj.x2 + 1 >= new_x) && (dx < 0)))
//			    		if ((obj.x1 <= new_x) && (obj.x2 >= new_x))
			    		{
							ty = obj.y1 + (x - obj.x1) * obj.dy / obj.dx;
			    			if ((ty - y >= - 4) && (ty - y <= 4))
			    			{
								curObj = obj;     // platform found
								new_y = ty;
								if (x < obj.x1)
								{
									new_x = obj.x1;
									new_y = obj.y1;
								}
								if (x > obj.x2)
								{
									new_x = obj.x2;
									new_y = obj.y2;
								}
								dy = dx = 0;
								if (class_type == T_A) dx = 1;
								isFalling = false;
								isFallen = true;
								started = true;
								jumpIndex = -1;
					    		phase = -1;
				    		}
			    		}
			    	}
			    	if (obj.type == Main.C_M)
			    	{
			    		if ((obj.mx - 8 <= new_x) && (obj.mx + 8 >= new_x) && (obj.my - 4 <= new_y) && (obj.my + 4 >= new_y))
			    		{
			    			curObj = obj;		// moving found
			    			new_y = obj.my;
			   	 			dx = dy = 0;
							if (class_type == T_A) dx = 1;
							isFalling = false;
							isFallen = true;
   							started = true;
							jumpIndex = -1;
				    		phase = -1;
		    			}
		    		}
			    	if (obj.type == Main.C_Lift)
			    	{
			    		if ((obj.x1 - (obj.fw >> 1) <= x) && (obj.x1 + (obj.fw >> 1) >= x) && 
			    			(obj.my - 4 <= y) && (obj.my + 4 >= y))
			    		{
			    			curObj = obj;		// moving found
			    			new_y = obj.my - 4;
			   	 			dx = dy = 0;
							if (class_type == T_A) dx = 1;
							isFalling = false;
							isFallen = true;
   							started = true;
							jumpIndex = -1;
				    		phase = -1;
		    			}
		    		}
		    	}
		    	if ((obj.type == Main.C_Sucker) && (dy < 0))
		    	{
		    		if ((obj.x1 - 4 <= x) && (obj.x1 + 4 >= x) && (obj.y1 >= y - frame.h) && (obj.y1 <= y))
		    		{
		    			y_border = obj.y1;
		    			curObj = obj;
		    			phase = 0;
    					new_x = curObj.x1;
		    			dx = 0;
		    			jumpIndex = -1;
		    			isFalling = false;
		    		}
		    	}
		    }
		    if ((curObj == null) && (jumpIndex == -1) && (y < Main.a_h)) isFalling = true;
	    }

		// falling check
    	if (isFalling)
	    {
	    	dy = Main.step;
	    	if (y - min_y > 20) dy++;
	    	if (y - min_y > 60) dy++;
	    	new_y = y + dy;
//	    	new_x = x;
//		    dx = 0;
		}

		if ((Main.state == 0) || (class_type != T_M))
		{
			// update animations indices 0,1  2,3  4,5  6,7
			if ((dy == 0) || (curObj == null))
			{
				if (dx < 0) 
					a1 = isFalling ? 0:2;
				else
				if (dx > 0) 
					a1 = isFalling ? 1:3;
				else
				{
					if ((a1 == 0) || (a1 == 2) || (a1 == 8)) a1 = 0;
					else a1 = 1;
				}
			}

			if ((curObj != null) && (dy == 0))
				if (curObj.type == Main.C_S)
				{
					a1 = 12;
				}

			if ((jumpIndex != -1) || (phase == 4))
			{
				if ((dx < 0) || (a1 == 0)) a1 = 8;
				if ((dx > 0) || (a1 == 1)) a1 = 9;
			}

			if ((isFallen) && (class_type == T_M))
			{
    			if ((new_y - min_y > 40) || (new_y + 1 >= Main.a_h)) crash();
			}

			if (phase == 5) a1 = 13;	// into teleport
			if (phase == 6) a1 = 14;    // out of teleport
		}
		cb();
	}

	void crash()
	{
		Main.beep(1);
		Main.state = 30;
		dx = dy = 0;
		if ((a1 == 0) || (a1 == 2) || (a1 == 8)) a1 = 10;
		else a1 = 11;
		a2 = 1;
		finished = false;
		loop = false;
	}

	void cb()
	{
		// check bounds
       	sdx = new_x - x;
       	sdy = new_y - y;

	    x = new_x;
	    y = new_y;

    	if (x < 0)
    	{
    		x = 0;
    		dx = 0;
    	}
    	if (x > Main.a_w)
    	{
    		x = Main.a_w;
    		dx = 0;
    	}
    	if (y < 0)
    	{
    		y = 0;
    		dy = 0;
    	}
    	if (y > Main.a_h)
    	{
    		y = Main.a_h;
    		dy = 0;
    		isFalling = false;
    	}
	}

    void draw()
    {
    	if ((class_type == T_B) && (inUse == true))
    	{
    		if ((Main.man.phase >= 0) && (Main.man.phase < 4)) return;
    	}
		if ((frame != null) && visible)
		{
			tx = x - Main.a_x_d - (frame.fw >> 1);
			ty = y - Main.a_y_d - frame.fh;
//			if (class_type == T_B) ty -= 2;
	  		if ((tx > - frame.fw) && (ty > - frame.fh) && (tx < Main.s_w) && (ty < Main.s_h))
	  		{
				image_index = 0;
				try
				{
			  		if (a != null)
  					{
  						b = a[a1];
		  				if (b != null)
		  				{
							if (a2 >= b.length) a2 = 1;
							image_index = b[a2];
							delay = b[0];
							if ((class_type == T_A) || (class_type == T_T))
								if ((dx > 1) || (dx < -1)) delay = b[0] - 1;
			 				if (time > delay)
			  				{
			  					if ((class_type == T_T) && (type > 0))
			  					{
			  						if (a2 == 1)
			  						{
			  							if (delay2 > 0) delay2--;
			  							else
			  							{
			  								delay2 = delay_range + Main.rnd(delay_range);
			  								a2++;
			  							}
			  						}
			  						else a2++;
			  					}
			  					else
			  					if ((class_type == T_T) && (type == 0))
			  					{
			  						if (alarm)
			  						{
			  							if (a2 != 3)
			  							{
											if (b.length <= ++a2)
											{
												a2 = 3;
											}
										}
										else a2 = 3;
			  						}
			  						else
			  						{
			  							if (a2 != 1)
			  							{
											if (b.length <= ++a2)
											{
												a2 = 1;
											}
										}
										else a2 = 1;
			  						}
			  					}
			  					else a2++;
								if (b.length <= a2)
								{
									if (loop) a2 = 1;
									else visible = false;
									// a2 = b.length - 1;

									finished = true;
  								}
								time = 0;
							}
		 					time++;
 						}
		  			}
	  			}
	  			catch(Exception ex){System.out.println(ex + "");}
	  			if (phase == -1)
	  			{
		  			Main.g.setClip(tx,ty,frame.fw,frame.fh);
		  		}
		  		else
		  		{
		  			Main.g.setClip(tx,ty > (y_border - Main.a_y_d) ? ty : y_border - Main.a_y_d,frame.fw,frame.fh);
		  		}
	  			Main.g.drawImage(Main.img[frame.index],tx - image_index,ty,20);
	  		}
		}
    }
}

